﻿using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.OCR;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using Emgu.CV.Util;
using Sunny.UI;
using Sunny.UI.Win32;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Schema;
using static System.Net.Mime.MediaTypeNames;
using static System.Windows.Forms.MonthCalendar;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace PipeDetection.UI
{
    internal class EmguCvHelper
    {
        private static Tesseract tesseract_0= new Tesseract(System.Windows.Forms.Application.StartupPath + "\\tessdata", "eng", OcrEngineMode.Default) { PageSegMode = PageSegMode.SingleBlock    };
        /// <summary>
        /// 识别里程文字
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static string OCR(Bitmap image)
        {
            Image<Rgb, byte> image1 = new Image<Rgb, byte>((Bitmap)image);
            var image2 = image1.Convert<Gray, byte>();
            tesseract_0.Recognize(image2);
            return tesseract_0.GetText();
        }


        public static List<Point> FindEdge(Image<Bgr, byte> img)
        {
            #region 旧方法
            //var imgg=img.Convert<Gray, byte>();
            //imgg=imgg.ThresholdBinary(new Gray(100), new Gray(200));
            //var contours = new VectorOfVectorOfPoint();
            //Mat hierachy = new Mat();
            //CvInvoke.FindContours(imgg, contours, hierachy, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
            //List<VectorOfPoint> hulls = new List<VectorOfPoint>();

            //for (int i = 0; i < contours.Size; i++)
            //{
            //    VectorOfPoint contour = contours[i];
            //    VectorOfPoint hull=new VectorOfPoint();
            //    CvInvoke.ConvexHull(contour, hull);
            //    VectorOfPoint simplify=new VectorOfPoint();
            //    CvInvoke.ApproxPolyDP(hull, simplify,50,true);//简化
            //    hulls.Add(simplify);

            //   }
            //var x = hulls.First(s => s.Size >= 3);
            //if (x != null)
            //{
            //    // img.Draw(x.ToArray(), new Bgr(Color.Red), 2);
            //    //Rectangle rec= CvInvoke.BoundingRectangle(x);
            //    var leftpt = x.ToArray().First(a => a.X == x.ToArray().Min(b => b.X));
            //    var rightpt = x.ToArray().First(a => a.X == x.ToArray().Max(b => b.X));
            //    var centpt = x.ToArray().First(a => a.Y == x.ToArray().Max(b => b.Y));

            //    List<Point> pts = new List<Point>() { leftpt, centpt, rightpt };
            //    return pts;
            //}
            #endregion



            //新方法
            Image<Hsv, byte> hsvImage = img.Convert<Hsv, byte>();

            VectorOfMat channels = new VectorOfMat(); //创建vectorOfmat类型存储分离后的图像
            CvInvoke.Split(hsvImage, channels); //通道分离
            InputOutputArray mix_channel = channels.GetInputOutputArray(); //获得数组

            //Mat H_channel = mix_channel.GetMat(0); //获得第一通道
            Mat S_channel = mix_channel.GetMat(1); //获得第二通道

            //var imgg = img.Convert<Gray, byte>();
            Mat dst1 = new Mat();
            CvInvoke.Threshold(S_channel, dst1, 40, 255, ThresholdType.Binary);

            VectorOfVectorOfPoint vvp = new VectorOfVectorOfPoint();
            //VectorOfVectorOfPoint use_vvp = new VectorOfVectorOfPoint();
            CvInvoke.FindContours(dst1, vvp, null, Emgu.CV.CvEnum.RetrType.List, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
            int number = vvp.ToArrayOfArray().Length;//取得轮廓的数量.
            var maxarea = 0d;
            VectorOfPoint maxpx =null;
            for (int i = 0; i < number; i++)
            {
                VectorOfPoint vp = vvp[i];
                double area = CvInvoke.ContourArea(vp);
                if (area > maxarea)
                {
                    maxarea = area;
                    maxpx = vp;
                }
            }
            VectorOfPoint x = new VectorOfPoint();
            CvInvoke.ConvexHull(maxpx, x);
            CvInvoke.ApproxPolyDP(x, x, 3, true);//简化
           
            //use_vvp.Push(hull);
            if (x != null)
            {
                // img.Draw(x.ToArray(), new Bgr(Color.Red), 2);
                //Rectangle rec= CvInvoke.BoundingRectangle(x);
                var leftpt = x.ToArray().First(a => a.X == x.ToArray().Min(b => b.X));
                var rightpt = x.ToArray().First(a => a.X == x.ToArray().Max(b => b.X));
                var centpt = x.ToArray().First(a => a.Y == x.ToArray().Max(b => b.Y));

                List<Point> pts = new List<Point>() { leftpt, centpt, rightpt };
                return pts;
            }
            


        

           return null;
        }
        public static Bitmap FindEdgeTest(Image<Bgr, byte> img)
        {
            //处理断面
            //闭运算

            Image<Bgr, byte> dst = img.CopyBlank();
            //定义内核的大小和形状，一般情况Size里的值为Point里对应的是的两倍加1
            Mat element = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(5, 5), new Point(2, 2));
            CvInvoke.MorphologyEx(img, dst, Emgu.CV.CvEnum.MorphOp.Close, element, new Point(1, 1), 1, Emgu.CV.CvEnum.BorderType.Default, new MCvScalar(255, 0, 0, 255));


          
            CvInvoke.MedianBlur(img, dst, 5);
            //阈值化
            CvInvoke.CvtColor(dst,dst,ColorConversion.Bgr2Gray);
            CvInvoke.Threshold(dst, dst, 30, 255, ThresholdType.Otsu | ThresholdType.Binary);

            //Mat dst1 = dst.Clone();

            //Mat skeleton = new Mat(dst1.Size, DepthType.Cv8U,1);
            
            //Mat subSkeleton = new Mat();
            //var kernel = CvInvoke.GetStructuringElement(ElementShape.Cross, new Size(5, 5), new Point(3, 3));
            //Mat opening=new Mat();

            //while (true)
            //{
            //    CvInvoke.Erode(dst1, dst1, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
            //    CvInvoke.MorphologyEx(dst1, opening, MorphOp.Open, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
            //    CvInvoke.Subtract(dst1, opening, subSkeleton);
            //    CvInvoke.BitwiseOr(skeleton, subSkeleton, skeleton);
            //    if (CvInvoke.CountNonZero(dst1) == 0)
            //    { break; }
            //}






            return dst.Bitmap;
        }

    }
}

